type corner = 
    {
      mutable xc : int;
      mutable yc : int;
    }

type rectangle = 
    {
      mutable top_left : corner;
      mutable top_right : corner;
      mutable bottom_right : corner;
      mutable bottom_left : corner;
    }

type imglist =
  |Space
  |Return
  |Img of Sdlvideo.surface
      

let empty_rect = {top_left = {xc = -1; yc = -1}; top_right = {xc = -1; yc = -1};
 bottom_left = {xc = -1; yc = -1}; bottom_right =  {xc = -1; yc = -1};};;

let char_rect recti = {top_left = {xc =  recti.top_left.xc; yc =  recti.top_left
.yc}; top_right = {xc = recti.top_left.xc; yc = recti.top_left.yc}; bottom_left
 = {xc =  recti.bottom_left.xc; yc =  recti.bottom_left.yc}; bottom_right =  {xc
 = recti.bottom_left.xc; yc = recti.bottom_left.yc};};;

let is_empty rect = rect.top_left.xc = -1 || rect.top_left.yc = -1 ||
 rect.top_right.xc = -1 || rect.top_right.yc = -1 || rect.bottom_left.xc = -1 ||
 rect.bottom_left.yc = -1 || rect.bottom_right.xc = -1 || 
rect.bottom_right.yc = -1

let clean_rect rect =
  begin
  rect.top_left.xc <- -1;
  rect.top_left.yc <- -1;
  rect.top_right.xc <- -1;
  rect.top_right.yc <- -1;
  rect.bottom_left.xc <- -1;
  rect.bottom_left.yc <- -1;
  rect.bottom_right.xc <- -1;
  rect.bottom_right.yc <- -1;
  end

let width_inf x y = function
  |{xc = -1; yc = -1} -> {xc = x; yc = y}
  |{xc = a; yc = b} ->
    begin
      if x < a then {xc = x; yc = b} else {xc = a; yc = b}
    end

let width_sup x y = function
  |{xc = -1; yc = -1} -> {xc = x; yc = y;}
  |{xc = a; yc = b} -> 
    begin
      if x > a then {xc = x; yc = b} else {xc = a; yc = b}
    end

let height_inf x y = function
  |{xc = -1; yc = -1} -> {xc = x; yc = y;}
  |{xc = a; yc = b} -> 
    begin
      if y > b then {xc = a; yc = y} else {xc = a; yc = b}
    end

let height_sup x y = function
  |{xc = -1; yc = -1} -> {xc = x; yc = y;}
  |{xc = a; yc = b} -> 
    begin
      if y < b then {xc = a; yc = y} else {xc = a; yc = b}
    end



let draw_rect rect dst color = 
  for i = rect.top_left.xc to rect.top_right.xc do
    Sdlvideo.put_pixel_color dst i rect.top_left.yc color;
  done;
  for i = rect.top_left.yc to rect.bottom_left.yc do
      Sdlvideo.put_pixel_color dst rect.top_left.xc i color;
  done;
  for i = rect.bottom_left.xc to rect.bottom_right.xc do
    Sdlvideo.put_pixel_color dst i rect.bottom_left.yc color;
  done;
  for i = rect.top_right.yc to rect.bottom_right.yc do
      Sdlvideo.put_pixel_color dst rect.top_right.xc i color;
  done

let is_black img (x,y) = 
  match Sdlvideo.get_pixel_color img x y with
    |(r,g,b) -> if (r < 10 && g < 10 && b < 10) then true else false

let rec is_present elt = function
  |[] -> false
  |e::l -> if e = elt then true else false || is_present elt l

let rec make_pixel_list img (x,y) pixel_list =
  let w = (Sdlvideo.surface_info img).Sdlvideo.w in
  let h = (Sdlvideo.surface_info img).Sdlvideo.h in
  if x > 0 && y > 0 && x < w-1 && y < h-1 then
    match (is_black img (x,y)) && not(is_present (x,y) !pixel_list) with
      |false -> ()
      |true -> begin
	pixel_list := (x,y)::(!pixel_list);
	  begin
	    make_pixel_list img (x,y+1) pixel_list;
	    make_pixel_list img (x,y-1) pixel_list;
	    make_pixel_list img (x+1,y-1) pixel_list;
            make_pixel_list img (x+1,y) pixel_list;
            make_pixel_list img (x+1,y+1) pixel_list;

	    (*make_pixel_list img (x-1,y-1) pixel_list;*)
	    (*make_pixel_list img (x-1,y+1) pixel_list;*)
	    (*make_pixel_list img (x-1,y) pixel_list;*)
	  end
      end
	
let init_rect rect (x,y) =
  begin
    rect.top_left.xc <- x;
    rect.top_left.yc <- y;
    
    rect.top_right.xc <- x;
    rect.top_right.yc <- y;
    
    rect.bottom_left.xc <- x;
    rect.bottom_left.yc <- y;
    
    rect.bottom_right.xc <- x;
    rect.bottom_right.yc <- y;
  end

let rec make_connected_rectangle rect list = match list with
  |[] -> ()
  |(x,y)::l -> 
    begin
      if x < rect.top_left.xc then
	begin
	  rect.top_left.xc <- x;
	  rect.bottom_left.xc <- x;
	end;
      if x > rect.top_right.xc then
	begin
	  rect.top_right.xc <- x;
	  rect.bottom_right.xc <- x;
	end;
      if y < rect.top_left.yc then
	begin
	  rect.top_left.yc <- y;
	  rect.top_right.yc <- y;
	end;
      if y > rect.bottom_left.yc then
	begin
	  rect.bottom_left.yc <- y;
	  rect.bottom_right.yc <- y;
	end;
      make_connected_rectangle rect l;
    end 

  
let rec draw_list dst color = function
  |[] -> ()
  |(x,y)::l -> begin
    Sdlvideo.put_pixel_color dst x y color;
    draw_list dst color l;
  end

let rec char_segmentation2 img dst rect top_leftx top_lefty img_char_list bool =
  begin 
    let not_found = ref true in
    let pixel_black = ref (0,0) in
    let counter = ref 0 in
    begin
      let i = ref top_leftx in
      while !not_found && !i < rect.top_right.xc do
	begin
	  let j = ref top_lefty in
	  while !not_found && !j < rect.bottom_left.yc do
	    begin
	      if is_black img (!i,!j) then
		begin
		  pixel_black := (!i,!j);
		  not_found := false;
		end;
	      j := !j + 1;
	    end
	  done;
	  if not(is_black img (!i, !j)) then
	    counter := (!counter)+1;
	  i := !i+1;
	end
      done
    end;
    if !pixel_black <> (0,0) then
      begin
	let pixel_list = ref [] in
	make_pixel_list img !pixel_black pixel_list;	
	let rect_char = {top_left = {xc = -1; yc = -1}; top_right = {xc = -1; yc
 = -1}; bottom_left = {xc = -1; yc = -1}; bottom_right =  {xc = -1; yc = -1};} 
 in
	init_rect rect_char !pixel_black;
	make_connected_rectangle rect_char !pixel_list;
	if bool then
	  draw_rect rect_char dst (255,0,255);

	let rect_char_w = rect_char.top_right.xc - rect_char.top_left.xc in
	let rect_char_h = rect_char.bottom_left.yc - rect_char.top_left.yc in
	let char_surface = Sdlvideo.create_RGB_surface [`SWSURFACE] (rect_char_w
) (rect_char_h) 32 (Int32.zero) (Int32.zero) (Int32.zero) (Int32.zero) in
	for j = 0 to rect_char_h-1 do
	  for i = 0 to rect_char_w-1 do
	    begin
	      Sdlvideo.put_pixel_color char_surface i j 
(Sdlvideo.get_pixel_color img (rect_char.top_left.xc+i) 
(rect_char.top_left.yc+j));
	    end
	  done;
	done;
	
	if !counter > ((rect.bottom_left.yc-rect.top_left.yc)/6) then
	  begin
	    img_char_list := Space::(!img_char_list)
	  end;
		  
	img_char_list := (Img (char_surface))::(!img_char_list);
	char_segmentation2 img dst rect (rect_char.top_right.xc+1) rect.top_left
.yc img_char_list bool;
      end
  end
      

let char_segmentation  img dst recti =
  let rect = char_rect recti in
  let anc_white_column = ref false in
  for x = recti.top_left.xc to recti.top_right.xc do
    let white_column = ref true in
    for y = recti.top_left.yc to recti.bottom_left.yc do
      begin
	let pixel_color = Sdlvideo.get_pixel_color img x y in
	if pixel_color = (0,0,0) then
	  begin
	    white_column := false;
	    Sdlvideo.put_pixel_color dst x y pixel_color;
	  end
	else
	  begin
	    Sdlvideo.put_pixel_color dst x y pixel_color;
	  end
      end
    done;
    if !white_column || x = recti.top_right.xc then
      begin
	(*draw_rect rect dst (0,0,255);*)
      end
    else (* black column *)
      begin
	if !anc_white_column then
	  begin
	    rect.top_left <- {xc = x; yc = recti.top_left.yc};
	    rect.bottom_left <- {xc = x; yc = recti.bottom_left.yc};
	  end;
	rect.top_right <- {xc = x; yc = recti.top_left.yc};
	rect.bottom_right <- {xc = x; yc = recti.bottom_left.yc};
      end;
    anc_white_column := !white_column;
  done

let line_segmentation img dst bool =
  let rect = empty_rect in
  let img_char_list = ref [] in
  let average = ref 0 in
  let (w,h) = Preprocess.get_dims img in
  for y = 0 to h-1 do
    let white_line = ref true in
    for x = 0 to w-1 do
      let pixel_color = Sdlvideo.get_pixel_color img x y in
      if pixel_color = (0,0,0) then
	begin
	white_line := false;

	rect.top_left <- width_inf x y rect.top_left;
	rect.top_left <- height_sup x y rect.top_left;
	rect.top_right <- width_sup x y rect.top_right;
	rect.top_right <- height_sup x y rect.top_right;
	rect.bottom_left <- width_inf x y rect.bottom_left;
	rect.bottom_left <- height_inf x y rect.bottom_left;
	rect.bottom_right <- width_sup x y rect.bottom_right;
	rect.bottom_right <- height_inf x y rect.bottom_right;
	end
      else
	begin
	  Sdlvideo.put_pixel_color dst x y pixel_color;
	end
    done;
    if (!white_line) && not (is_empty rect) then
      begin
	char_segmentation2 dst dst rect rect.top_left.xc rect.top_left.yc 
	  img_char_list bool;
	if bool then
	  draw_rect rect dst (0,0,255);
	img_char_list := Return::(!img_char_list);
	clean_rect rect;
	average := 0;
      end
  done;
  !img_char_list
    

let segmentation img dst bool = 
  line_segmentation img dst bool

